package com.fatri.lessionsimple.opengl.drawer

import android.content.Context
import android.opengl.GLES20
import android.opengl.Matrix
import com.fatri.lessionsimple.opengl.IDrawer
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer

/**
 * 带相机变换矩阵的正方体
 */
class CubeDrawer(ctx: Context) : IDrawer(ctx) {


    private val vertexShaderCode = "attribute vec4 vPosition;" +
            "uniform mat4 vMatrix;" +
            "varying  vec4 vColor;" +
            "attribute vec4 aColor;" +
            "void main() {" +
            "  gl_Position =  vMatrix*vPosition;" +
            "vColor=aColor;" +
            "}"

    private val fragmentShaderCode = "precision mediump float;" +
            "varying vec4 vColor;" +
            "void main() {" +
            "  gl_FragColor = vColor;" +
            "}"

    private var mProgram = 0
    private lateinit var vertexBuffer: FloatBuffer


    val COORDS_PER_VERTEX = 3

    //立方体八个顶点
    var triangleCoords = floatArrayOf(
        //前面Z都是0.5，后面Z都是-0.5
        -1f, 1f, 1f,    //前面左上
        1f, 1f, 1f,     //前面右上
        1f, -1f, 1f,    //前面右下
        -1f, -1f, 1f,  //前面左下

        -1f, 1f, -1f,    //后面左上
        1f, 1f, -1f,     //后面右上
        1f, -1f, -1f,    //后面右下
        -1f, -1f, -1f    //后面左下

    )


    //使用顶点复用绘制，GL_TRIANGLES方式，每三个点单独绘制一个三角形
    //六个面，每个面两个三角形，六个点
    var indexArr = shortArrayOf(
        3,2,7,2,7,6,//bottom
        4, 5, 7, 5, 7, 6,//back
        1, 2, 5, 2,5,6 ,//right
        0,3,4,3,4,7,//left
        0,1,3,1,3,2,
        0,1,4,1,4,5//top
    )



    private var mPositionHandle = 0
    private var mColorHandle = 0


    //顶点个数
    private val vertexCount = triangleCoords.size / COORDS_PER_VERTEX

    //一个顶点占有的总字节数
    private val vertexStride = COORDS_PER_VERTEX * 4 // 每个顶点包括3个float，一个float四字节


    private val mViewMatrix = FloatArray(16)
    private val mProjectMatrix = FloatArray(16)
    private val mMVPMatrix = FloatArray(16)


    //设置颜色
    var color = floatArrayOf(
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        0f, 1f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f,
        1f, 0f, 0f, 1f
    )
    lateinit var colorBuffer: FloatBuffer
    lateinit var indexBuffer: ShortBuffer
    override fun onSurfaceCreated() {
        //开启深度测试
        GLES20.glEnable(GLES20.GL_DEPTH_TEST)  //不开启时，后面绘制的面会覆盖前面的，开启自动识别距相机的前后

        triangleCoords.forEach { it * 2 }

        val bb = ByteBuffer.allocateDirect(triangleCoords.size * 4)
        bb.order(ByteOrder.nativeOrder())
        vertexBuffer = bb.asFloatBuffer()
        vertexBuffer.put(triangleCoords)
        vertexBuffer.position(0)


        //转换颜色着色器数据
        val cc = ByteBuffer.allocateDirect(color.size * 4)
        cc.order(ByteOrder.nativeOrder())
        colorBuffer = cc.asFloatBuffer()
        colorBuffer.put(color)
        colorBuffer.position(0)


        val ss = ByteBuffer.allocateDirect(indexArr.size * 2)
        ss.order(ByteOrder.nativeOrder())
        indexBuffer = ss.asShortBuffer()
        indexBuffer.put(indexArr)
        indexBuffer.position(0)


        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        val fragShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)

        mProgram = GLES20.glCreateProgram()
        GLES20.glAttachShader(mProgram, vertexShader)
        GLES20.glAttachShader(mProgram, fragShader)
        GLES20.glLinkProgram(mProgram)


    }

    override fun onSurfaceChanged(width: Int, height: Int) {
        val ratio = (width * 1.0 / height).toFloat()

//        //设置透视投影
//        Matrix.frustumM(
//            mProjectMatrix, 0
//            , -ratio, ratio, -1f, 1f, 3f, 7f
//        )
//        //设置相机位置
//        Matrix.setLookAtM(
//            mViewMatrix, 0,
//            0f, 0f, 7.0f,   //eyeZ=7表示相机位置设置在目标正前方
//            0f, 0f, 0f,//目标的坐标
//
//            0.0f, 1.0f, 0.0f
//        )  //up为三个向量，合成的方向才是相机最终的方向，
//        //若（0，1，0）为正视目标，则（1，1，0）旋转了45°
//        //计算变换矩阵
//        Matrix.multiplyMM(
//            mMVPMatrix, 0,
//            mProjectMatrix, 0,
//            mViewMatrix, 0
//        )

        //设置透视投影
        Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 20f)
        //设置相机位置
        Matrix.setLookAtM(
            mViewMatrix,
            0,
            5.0f,
            5.0f,
            8.0f,
            0f,
            0f,
            0f,
            0.0f,
            1.0f,
            0.0f
        )
        //计算变换矩阵
        //计算变换矩阵
        Matrix.multiplyMM(mMVPMatrix, 0, mProjectMatrix, 0, mViewMatrix, 0)
    }

    override fun onDrawFrame() {

        GLES20.glUseProgram(mProgram)
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition")
        GLES20.glEnableVertexAttribArray(mPositionHandle)
        GLES20.glVertexAttribPointer(
            mPositionHandle,
            COORDS_PER_VERTEX,  //顶点数据个数
            GLES20.GL_FLOAT,
            false,
            vertexStride, //顶点占有的字节总数
            vertexBuffer
        )

        //给vMatrix赋值
        val mMatrixHandler = GLES20.glGetUniformLocation(mProgram, "vMatrix")
        GLES20.glUniformMatrix4fv(mMatrixHandler, 1, false, mMVPMatrix, 0)

        //给aColor赋值
        val colorHandler = GLES20.glGetAttribLocation(mProgram, "aColor")
        GLES20.glEnableVertexAttribArray(colorHandler)
        GLES20.glVertexAttribPointer(
            colorHandler, 4, GLES20.GL_FLOAT, false,
            0, colorBuffer
        )


//        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, vertexCount)

        GLES20.glDrawElements(
            GLES20.GL_TRIANGLE_STRIP,
            indexArr.size,
            GLES20.GL_UNSIGNED_SHORT,
            indexBuffer
        )
        //禁止顶点数组的句柄
        GLES20.glDisableVertexAttribArray(mPositionHandle)

    }

    override fun release() {
    }

}